package com.gtlab1207.br_security.services;


import com.gtlab1207.br_security.ctrls.CertManageCtrl;
import com.gtlab1207.br_security.models.dao.CertDao;
import com.gtlab1207.br_security.models.domain.Cert;
import com.taoyuanx.ca.core.api.ICA;
import com.taoyuanx.ca.core.api.impl.CAImpl;
import com.taoyuanx.ca.core.util.CertUtil;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;

/**
 * 生成用户证书业务层
 */
@Slf4j
@Service
public class CreateCertService {
    //签名算法位数
    static Integer keySize=2048;
    @Autowired
    CertDao certDao;
    /**
     * 生成用户公私钥,证书
     * @param CACert            CA的base64证书
     * @param privateKey        CA的私钥
     * @param alias             用户名                 SURNAME
     * @param password          密码
     * @param level             等级                   L
     * @param name              真实姓名                ST
     * @param role              角色                   UID
     * @param business          所属业务分类             OU
     * @param template          模板分类                T
     * @param email             电子邮箱                E
     * @param sex               性别                   CN
     * @param organization      所属组织机构             O
     * @return
     * @throws Exception
     */
    public boolean CreateCert(X509Certificate CACert, PrivateKey privateKey, String alias, String password,
                              String level, String name, String role, String business, String template,
                              String email, String sex, String organization) throws Exception {
        //用户证书的DN
        String userDN="SURNAME="+ alias +",L=" + level + ",ST=" + name + ",UID=" + role +
                ",OU=" + business + ",T=" + template + ",E=" + email +",CN=" + sex + ",O=" + organization;

        String baseCertPath="/Users/shier/Documents/cert/rsa/"+alias; //创建用户证书的目录
        File clientDir=new File(baseCertPath); //生成用户client子目录路径
        // 判断是否已有相同alias
        if(clientDir.exists()) {
            log.error("{} create cert error!", alias);
            return false;
        }else {
            //创建证书存放目录
            clientDir.mkdirs();
        }

        ICA ica=new CAImpl();
        ica.config(CACert,privateKey);

        KeyPair keyPair = CreateKeyPair();
        Date notBefore=new Date();
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.YEAR, 1);
        Date notAfter=instance.getTime();
        BigInteger serialNumber=BigInteger.valueOf(1L);
        String signAlg=CAImpl.DEFAULT_SIGN_ALG;

        // 将证书记录到数据库里
        Cert cert = new Cert(alias,baseCertPath,new Date());
        certDao.insertCert(cert);

        X509Certificate x509Certificate = ica.makeUserCert(
                keyPair.getPublic(), CACert.getIssuerDN().toString(), userDN, notBefore, notAfter, serialNumber, signAlg);

        CertUtil.saveX509CertBase64(x509Certificate, baseCertPath+"/"+alias+"_base64.cer");
        CertUtil.saveX509CertBinary(x509Certificate, baseCertPath+"/"+alias+".cer");
        CertUtil.savePrivateKeyPem(keyPair.getPrivate(), baseCertPath+"/"+alias+"_pri.pem");
        CertUtil.savePublicKeyPem(keyPair.getPublic(), baseCertPath+"/"+alias+"_pub.pem");
        CertUtil.savePKCS12(x509Certificate, keyPair.getPrivate(), alias, password, baseCertPath+"/"+alias+".p12");

        return true;
    }

    /**
     * 创建密钥对生成器
     * @return
     * @throws Exception
     */
    public KeyPair CreateKeyPair() throws Exception {
        KeyPairGenerator kpg=kpg=KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
        kpg.initialize(keySize);
        KeyPair keyPair = kpg.generateKeyPair();
        return keyPair;
    }

}
